package com.haojiang.mh.widget.chart;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.haojiang.mh.R;
import com.haojiang.mh.service.entity.*;
import com.haojiang.mh.utils.ImageUtil;
import com.haojiang.mh.utils.MUtil;
import com.haojiang.mh.utils.SizeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * 双层（柱状背景+曲线上层）
 * 当前用在《止鼾枕日报图》
 */
public class SignSnoreChartView extends View {

    private TextPaint textPaint;
    //坐标刻度、柱状条、线条、遮罩层 打鼾圆 干扰线 画笔
    private Paint coordinatePaint, columnPaint, linePaint, coverPaint, snoreCirclePaint, interruptPaint;
    private int columnNumber;//时间段数量
    private int startCoordinate = -1, endCoordinate = -1;//开始坐标和结束坐标
    //当前View的宽、高、默认宽、默认高、绘制区域高度、顶部间隔
    private int width, height, defaultWidth, defaultHeight, drawHeight, paddingTop;
    //X轴文字宽度、X轴文字高度、X轴高度、Y轴文字高度、Y轴宽度
    private int xAxisTextWidth, xAxisTextHeight, xAxisHeight, yAxisTextHeight, yAxisWidth;
    //通用、遮罩层、遮罩层、遮罩层线条、曲线对应颜色
    private int commonColor, coverColor, coverLineColor, curveColor, circleColor;
    private int bottomY;//Y坐标起始点位置
    private int centerY;//Y坐标轴中间点位置
    private int snoreInterruptIconMargin; //打鼾图标和线的间隔
    private float xItemWidth, yItemHeight;//X轴间隔款、Y轴间隔高度
    //Y轴起始坐标、坐标间隔、除起点外坐标个数、最大值坐标
    private int yStartCoordinate, yInterval, yCoordinateNum, yMaxCoordinate;
    private int minSnoreCircleRadius; //打鼾圆最小半径
    private int maxSnoreCircleRadius; //打鼾圆最大半径
    private boolean isCover = true;//是否有最佳遮罩
    private boolean is24HourXAxis = false;//X轴是否为默认24小时(环境报表使用)
    private Bitmap snoreInterruptBitmap, snoreInterceptFailBitmap; //止鼾图标

    private List<StartEndStateBean> sleepList;//背景数据集
    private List<TimeValueBean> beanList;//打鼾圆数据集
    private List<InterveneBean> interventionList; //干扰线数据集
    private List<InterveneBean> interventionFailList; //干扰失败线数据集
    private Bitmap noDataBitmap;

    public SignSnoreChartView(Context context) {
        this(context, null);
    }

    public SignSnoreChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SignSnoreChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        @SuppressLint("CustomViewStyleable")
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChartModuleAttribute, defStyleAttr, 0);
        yStartCoordinate = a.getInt(R.styleable.ChartModuleAttribute_cm_y_start, 0);
        yInterval = a.getInt(R.styleable.ChartModuleAttribute_cm_y_interval, 10);
        yCoordinateNum = a.getInt(R.styleable.ChartModuleAttribute_cm_y_number, 10);
        isCover = a.getBoolean(R.styleable.ChartModuleAttribute_cm_is_cover, true);
        is24HourXAxis = a.getBoolean(R.styleable.ChartModuleAttribute_cm_is_24_x, false);
        a.recycle();

        initView(context);
    }

    private void initView(Context context) {
        xAxisTextWidth = SizeUtil.dp2px(context, 40);
        xAxisTextHeight = SizeUtil.dp2px(context, 40);
        xAxisHeight = SizeUtil.dp2px(context, 3);
        yAxisTextHeight = SizeUtil.dp2px(context, 25);
        yAxisWidth = SizeUtil.dp2px(context, 40);
        paddingTop = SizeUtil.dp2px(context, 20);
        drawHeight = SizeUtil.dp2px(context, 150);
        snoreInterruptIconMargin = SizeUtil.dp2px(getContext(), 10);
        minSnoreCircleRadius = SizeUtil.dp2px(getContext(), 5);
        maxSnoreCircleRadius = (int) (drawHeight * 0.8);

        noDataBitmap = ImageUtil.getBitmapFromDrawable(context, R.drawable.img_no_chart_data);
        snoreInterruptBitmap = ImageUtil.getBitmapFromDrawable(getContext(), R.drawable.ic_snore_intercept);
//        snoreInterruptBitmap = ImageUtil.getBitmapFromDrawable(getContext(), R.drawable.ic_stop_snore_success);
        snoreInterceptFailBitmap = ImageUtil.getBitmapFromDrawable(getContext(), R.drawable.ic_stop_snore_fail);
        defaultWidth = SizeUtil.dp2px(context, 340);
        defaultHeight = noDataBitmap.getHeight();

        commonColor = getResources().getColor(R.color.grey_2);
        coverColor = getResources().getColor(R.color.purple_3) & 0x4CFFFFFF;
        circleColor = getResources().getColor(R.color.purple_5);
        coverLineColor = getResources().getColor(R.color.white) & 0x19FFFFFF;
        curveColor = getResources().getColor(R.color.purple_3);

        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(SizeUtil.sp2px(context, 11));
        textPaint.setColor(commonColor);

        coordinatePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        coordinatePaint.setStyle(Paint.Style.FILL);
        coordinatePaint.setStrokeWidth(3);
        coordinatePaint.setColor(commonColor);

        columnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        columnPaint.setStyle(Paint.Style.FILL);

        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setStyle(Paint.Style.STROKE);

        if (!isCover) return;
        coverPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        coverPaint.setStyle(Paint.Style.FILL);
        coverPaint.setColor(coverColor);

        snoreCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        snoreCirclePaint.setStyle(Paint.Style.FILL);
        snoreCirclePaint.setColor(circleColor);

        interruptPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        interruptPaint.setStyle(Paint.Style.FILL);
        interruptPaint.setColor(curveColor);
        interruptPaint.setStrokeWidth(3);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (sleepList == null || (!is24HourXAxis && sleepList.isEmpty())) {
            canvas.drawBitmap(noDataBitmap, (width - noDataBitmap.getWidth()) * 0.5f, 0, linePaint);
            return;
        }

        xItemWidth = (float) (width - yAxisWidth) / columnNumber;
        yItemHeight = (float) drawHeight / (2 * yCoordinateNum);
        yMaxCoordinate = yStartCoordinate + yCoordinateNum * yInterval;
        bottomY = height - xAxisTextHeight - xAxisHeight;
        centerY = bottomY - drawHeight / 2;

        /* 绘制Y轴 */
        drawYAxis(canvas);

        if (beanList != null && !beanList.isEmpty()) {
            /* 绘制打鼾圆 */
            drawSnoreCircle(canvas);
        }
        if (startCoordinate != -1 && endCoordinate != -1) {
            /* 绘制X轴 */
            drawXAxis(canvas);
        }

        /* 绘制干扰线 */
        drawInterruptLine(canvas);
    }

    /**
     * 绘制X轴
     */
    private void drawXAxis(Canvas canvas) {
        if (is24HourXAxis) {
            for (int i = 0; i < 25; i++) {//从左至右
                canvas.drawLine(i * xItemWidth, bottomY, i * xItemWidth, bottomY + xAxisHeight, coordinatePaint);
                if (i == 0 || i == 24 || i % 3 != 0) continue;
                canvas.drawText(
                        String.format(Locale.getDefault(), "%02d:00", (i + 18) % 24),
                        xItemWidth * i,
                        SizeUtil.getBaseLine(textPaint, height, xAxisTextHeight),
                        textPaint
                );
            }
            return;
        }
        int interval;
        if (columnNumber <= 6) {
            interval = 1;
        } else if (columnNumber <= 18) {
            interval = 2;
        } else {
            interval = 3;
        }
        if (columnNumber == 1) {//只有一个小时，左右刻度+左右靠边时间点
            canvas.drawLine(0, bottomY, 0, bottomY + xAxisHeight, coordinatePaint);
            canvas.drawLine(width - yAxisWidth, bottomY, width - yAxisWidth, bottomY + xAxisHeight, coordinatePaint);//刻度线
            canvas.drawText(//最左侧刻度
                    String.format(Locale.getDefault(), "%02d:00", startCoordinate % 24),
                    xAxisTextWidth * 0.5f,
                    SizeUtil.getBaseLine(textPaint, height, xAxisTextHeight),
                    textPaint
            );
            canvas.drawText(//最右侧刻度
                    String.format(Locale.getDefault(), "%02d:00", endCoordinate % 24),
                    width - yAxisWidth - xAxisTextWidth / 2,
                    SizeUtil.getBaseLine(textPaint, height, xAxisTextHeight),
                    textPaint
            );
        } else {//绘制所有刻度以及除顶末端的刻度文字
            for (int i = 0; i <= columnNumber; i++) {
                canvas.drawLine(i * xItemWidth, bottomY, i * xItemWidth, bottomY + xAxisHeight, coordinatePaint);
                if (i != 0 && i != columnNumber && i % interval == 0) {
                    canvas.drawText(
                            String.format(Locale.getDefault(), "%02d:00", (startCoordinate + i) % 24),
                            xItemWidth * i,
                            SizeUtil.getBaseLine(textPaint, height, xAxisTextHeight),
                            textPaint
                    );
                }
            }
        }
    }

    /**
     * 绘制Y轴
     */
    private void drawYAxis(Canvas canvas) {
        for (int i = 0; i <= yCoordinateNum; i++) {
            if (i == 0) {
                canvas.drawCircle(width - yAxisWidth, centerY, 5, coordinatePaint);//刻度点
                continue;
            }
            float yUpItemMidPos = centerY - yItemHeight * i;
            float yDownItemMidPos = centerY + yItemHeight * i;
            canvas.drawCircle(width - yAxisWidth, yUpItemMidPos, 5, coordinatePaint);//刻度点
            canvas.drawCircle(width - yAxisWidth, yDownItemMidPos, 5, coordinatePaint);//刻度点
            canvas.drawText(//X轴上部分
                    String.valueOf(yStartCoordinate + i * yInterval),
                    width - yAxisWidth * 0.5f,
                    SizeUtil.getBaseLine(textPaint, yUpItemMidPos + yAxisTextHeight * 0.5f, yAxisTextHeight),
                    textPaint
            );
            canvas.drawText(//X轴上部分
                    String.valueOf(yStartCoordinate + i * yInterval),
                    width - yAxisWidth * 0.5f,
                    SizeUtil.getBaseLine(textPaint, yDownItemMidPos + yAxisTextHeight * 0.5f, yAxisTextHeight),
                    textPaint
            );
        }
    }

    /**
     * 绘制打鼾圆
     */
    private void drawSnoreCircle(Canvas canvas) {
        for (int i = 0; i < beanList.size(); i++) {
            TimeValueBean timeValueBean = beanList.get(i);
            int value = timeValueBean.getValue();
            if (value > 0) {
                int radius = minSnoreCircleRadius + value > maxSnoreCircleRadius ? maxSnoreCircleRadius : minSnoreCircleRadius + value;
                radius = (int) Math.pow(radius, 1.0 / 1.1); //开方运算
                canvas.drawCircle(getXCoordinate(timeValueBean.getTime()), centerY, radius, snoreCirclePaint);
            }
        }

    }

    /**
     * 绘制干扰线
     */
    private void drawInterruptLine(Canvas canvas) {
        if (snoreInterruptBitmap == null) {
            return;
        }
      /*  if (interventionFailList != null) {
            interruptPaint.setColor(ResourceUtil.getColor(R.color.yellow_end));
            for (int i = 0; i < interventionFailList.size(); i++) {
                DaySnoreCycleResult.Intervention intervention = interventionFailList.get(i);
                float x = getXCoordinate(intervention.getTime());
                float y = bottomY - drawHeight - snoreInterruptIconMargin - snoreInterceptFailBitmap.getHeight();
                canvas.drawLine(x, bottomY, x, bottomY - drawHeight - snoreInterruptIconMargin, interruptPaint);
                canvas.drawBitmap(snoreInterceptFailBitmap, x - snoreInterceptFailBitmap.getWidth() / 2 - 1, y, null);
            }
        }*/
        if (interventionList != null) {
            interruptPaint.setColor(curveColor);
            for (int i = 0; i < interventionList.size(); i++) {
                InterveneBean ib = interventionList.get(i);
                float x = getXCoordinate(ib.getTime());
                float y = bottomY - drawHeight - snoreInterruptIconMargin - snoreInterruptBitmap.getHeight();
                canvas.drawLine(x, bottomY, x, bottomY - drawHeight - snoreInterruptIconMargin, interruptPaint);
                canvas.drawBitmap(snoreInterruptBitmap, x - snoreInterruptBitmap.getWidth() * 0.5f - 1, y, null);
            }
        }
    }

    /**
     * 获取时间轴坐标
     *
     * @param timeString 时间点
     * @return 相对x坐标点
     */
    private int getXCoordinate(String timeString) {
        int duration = MUtil.INSTANCE.getTimeDuration(startCoordinate, timeString, "HH:mm");
        return duration * (width - yAxisWidth) / (3600 * columnNumber);
    }

    /**
     * 获取X轴坐标个数
     */
    private void getXColumnNumber() {
        if (is24HourXAxis) {
            columnNumber = 24;
            startCoordinate = 18;
            endCoordinate = 18;
            return;
        }
        if (sleepList == null || sleepList.isEmpty()) return;
        String startTime = sleepList.get(0).getStart();
        if (TextUtils.isEmpty(startTime) || !startTime.contains(":")) {
            startCoordinate = -1;
            return;
        } else {
            startCoordinate = MUtil.INSTANCE.getHourAndMinute(startTime, "HH:mm")[0];
        }
        String endTime = sleepList.get(sleepList.size() - 1).getEnd();
        if (TextUtils.isEmpty(endTime) || !endTime.contains(":")) {
            endCoordinate = -1;
            return;
        } else {
            int[] endHM = MUtil.INSTANCE.getHourAndMinute(endTime, "HH:mm");
            endCoordinate = endHM[0] + (endHM[1] != 0 ? 1 : 0);
        }
        if (startCoordinate == endCoordinate) {
            columnNumber = 24;
        } else {
            columnNumber = endCoordinate - startCoordinate;
            if (endCoordinate < startCoordinate) columnNumber += 24;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(
                getMeasuredLength(widthMeasureSpec, true),
                getMeasuredLength(heightMeasureSpec, false)
        );
    }

    private int getMeasuredLength(int length, boolean isWidth) {
        int specMode = MeasureSpec.getMode(length);
        int specSize = MeasureSpec.getSize(length);
        int size;
        int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
        if (specMode == MeasureSpec.EXACTLY) {
            size = specSize;
        } else if (specMode == MeasureSpec.UNSPECIFIED) {
            size = isWidth ? defaultWidth : defaultHeight;
        } else {
            size = isWidth ? padding + defaultWidth : padding + defaultHeight;
            if (specMode == MeasureSpec.AT_MOST) {
                size = Math.min(size, specSize);
            }
        }
        return size;
    }

    public void setChartDataNew(List<StatusBean> bgData, List<TimeStampBean> circleData, List<TimeStampBean> interveneData) {
        if (sleepList == null) sleepList = new ArrayList<>();
        sleepList.clear();
        if (beanList == null) beanList = new ArrayList<>();
        beanList.clear();
        if (interventionList == null) interventionList = new ArrayList<>();
        interventionList.clear();

        if (interveneData != null && !interveneData.isEmpty()) {
            List<InterveneBean> tempList = new ArrayList<>();
            for (TimeStampBean tsb : interveneData) {
                InterveneBean ib = new InterveneBean();
                ib.setTime(MUtil.INSTANCE.getHM(tsb.getTime()));
                tempList.add(ib);
            }
            interventionList.addAll(tempList);
        }
        if (circleData != null && !circleData.isEmpty()) {
            List<TimeValueBean> tempList = new ArrayList<>();
            for (TimeStampBean tsb : circleData) {
                TimeValueBean tvb = new TimeValueBean();
                tvb.setTime(MUtil.INSTANCE.getHM(tsb.getTime()));
                tvb.setValue(tsb.getValue());
                tempList.add(tvb);
            }
            beanList.addAll(tempList);
        }
        if (bgData != null) {
            if (!bgData.isEmpty()) {
                List<StartEndStateBean> tempList = new ArrayList<>();
                for (StatusBean sb : bgData) {
                    StartEndStateBean ssb = new StartEndStateBean();
                    ssb.setStart(MUtil.INSTANCE.getHM(sb.getStart()));
                    ssb.setEnd(MUtil.INSTANCE.getHM(sb.getEnd()));
                    ssb.setStatus(sb.getStatus());
                    tempList.add(ssb);
                }
                sleepList.addAll(tempList);
            }
            getXColumnNumber();
        }

        int bitmapHeight = snoreInterruptBitmap == null ? 0 : snoreInterruptBitmap.getHeight();
        defaultHeight = paddingTop + drawHeight + xAxisHeight + xAxisTextHeight + bitmapHeight;
        requestLayout();
    }

    public void setChartData(List<StartEndStateBean> columnData, List<TimeValueBean> circleData, List<InterveneBean> interventionData, List<InterveneBean> failList) {
        if (sleepList == null) sleepList = new ArrayList<>();
        sleepList.clear();
        if (beanList == null) beanList = new ArrayList<>();
        beanList.clear();
        if (interventionList == null) interventionList = new ArrayList<>();
        interventionList.clear();
        if (interventionFailList == null) interventionFailList = new ArrayList<>();
        interventionFailList.clear();

        if (interventionData != null) interventionList.addAll(interventionData);
        if (failList != null) interventionFailList.addAll(failList);
        if (circleData != null && !circleData.isEmpty()) beanList.addAll(circleData);
        if (columnData != null) {
            if (!columnData.isEmpty()) sleepList.addAll(columnData);
            getXColumnNumber();
        }

        int bitmapHeight = snoreInterruptBitmap == null ? 0 : snoreInterruptBitmap.getHeight();
        defaultHeight = paddingTop + drawHeight + xAxisHeight + xAxisTextHeight + bitmapHeight;
        requestLayout();
    }

    public void showNoData() {
        if (sleepList == null) sleepList = new ArrayList<>();
        sleepList.clear();
        if (beanList == null) beanList = new ArrayList<>();
        beanList.clear();
        if (interventionList == null) interventionList = new ArrayList<>();
        interventionList.clear();
        if (interventionFailList == null) interventionFailList = new ArrayList<>();
        interventionFailList.clear();
        defaultHeight = noDataBitmap.getHeight();
        requestLayout();
    }
}
